﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LGE;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace UpUp
{
    public class PlayScreen : GameScreen
    {
        // variables
        int nLevels = 5;
        public int levelHeight = 40;

        // aux
        public int level = 0; // começa no level 0
        int H { get { return (int)-(c.position.Y / Tile.Size); } }
        bool isSnowing = true;
        bool showHotkeys = false;
        public int crystalsInThisSession = 0;
        public int HMaxInThisSession = 0;
        public bool finished = false;

        // components
        MarketScreen marketScreen = null;
        GameOverScreen gameOverScreen = null;
        public bool isMarket = false;
        public bool isLive = true;
        Texture2D background;
        Vector2 bgPos1, bgPos2;
        public BlockManager bm;
        public Character c;
        List<GameObject> gameObjects;
        public EffectsManager effectsManager;
        public EffectsManager snowFlakesManagerBack;
        public EffectsManager snowFlakesManagerFront;

        // Sound
        const String SFX_Folder = "Audio\\SFX\\";
        public String SFX_bgWind = SFX_Folder + "BGWind";
        public String SFX_Win = SFX_Folder + "End";
        SoundEffectInstance bgWindInstance;

        // HUD
        Texture2D barbg;
        Texture2D barhp;
        Texture2D heart;
        Texture2D ice;
        Vector2 barhpPos = new Vector2(53, 50);
        Vector2 barbgPos = new Vector2(51, 48);
        Vector2 heartPos = new Vector2(314, 34);
        Vector2 icePos = new Vector2(20, 20);

        public PlayScreen()
            : base()
        {
        }

        public override void LoadContent()
        {
            Audio.AddSFX(SFX_bgWind);
            Audio.AddSFX(SFX_Win);
            bgWindInstance = Audio.GetSFXInstance(SFX_bgWind);
            bgWindInstance.IsLooped = true;
            bgWindInstance.Play();
            barbg = Engine.Load<Texture2D>("Images\\PlayScreen\\barbg");
            barhp = Engine.Load<Texture2D>("Images\\PlayScreen\\barhp");
            heart = Engine.Load<Texture2D>("Images\\PlayScreen\\heart");
            ice = Engine.Load<Texture2D>("Images\\PlayScreen\\ice");
            background = Engine.Load<Texture2D>("Images\\PlayScreen\\background");
            bgPos1 = bgPos2 = Vector2.Zero;
            effectsManager = new EffectsManager();
            snowFlakesManagerBack = new EffectsManager();
            snowFlakesManagerFront = new EffectsManager();
            gameObjects = new List<GameObject>();
            c = new Character(this, Vector2.Zero);
            c.Load();
            marketScreen = new MarketScreen(this, c);
            marketScreen.LoadContent();
            bm = new BlockManager(this);
            bm.Load();
            GameObject.relativeObject = c;

            // atualiza 300 vezes a nevasca para que ela já comece com a tela cheia de flocos de neve
            for (int i = 0; i < 300; i++) UpdateBackgroundAndSnow(new GameTime(new TimeSpan(100000), new TimeSpan(100000)));
        }

        public override void Update(GameTime gameTime)
        {
            #region Cheat
            if (Input.KeyDown(Keys.LeftControl) &&
                Input.KeyDown(Keys.LeftAlt) &&
                Input.KeyPressed(Keys.Z))
            {
                Audio.PlaySFX(SFX_Win);
                UpUp.isDebug = !UpUp.isDebug;
            }

            #endregion
            if (finished)
            {
                if (gameOverScreen == null) gameOverScreen = new GameOverScreen();
                gameOverScreen.Update(gameTime);
                isLive = false;
            }

            UpdateBackgroundAndSnow(gameTime);
            c.Update(gameTime);
            bm.Update(gameTime); // deve vir depois do Update do character

            if (isMarket) { marketScreen.Update(gameTime); return; }
            // daqui pra baixo só acontece se não estiver na MarketScreen

            UpdateLevel();
            UpdateGameObjects(gameTime);
            effectsManager.Update(gameTime);

            if (UpUp.isDebug)
            {
                if (Input.KeyPressed(Keys.Enter)) isSnowing = !isSnowing;
                if (Input.KeyPressed(Keys.Back)) c.hp = -10000;
                if (Input.KeyPressed(Keys.F2)) showHotkeys = !showHotkeys;
            }

            if (!c.alive)
            {
                ScoreScreen scoreScreen = new ScoreScreen(this);
                scoreScreen.LoadContent();
                GameScreenManager.Push(scoreScreen, false);
            }

            if (Input.KeyPressed(Keys.M)) Audio.ToggleMute();

            if (H > HMaxInThisSession) { HMaxInThisSession = H; if (HMaxInThisSession > nLevels * levelHeight) HMaxInThisSession = nLevels * levelHeight; }
        }

        public void UpdateGameObjects(GameTime gameTime)
        {
            for (int i = 0; i < gameObjects.Count; ++i)
            {
                if (!gameObjects[i].alive)
                    gameObjects.RemoveAt(i);
                else
                    gameObjects[i].Update(gameTime);
            }
        }

        public void UpdateBackgroundAndSnow(GameTime gameTime)
        {
            //Vector2 drawPosition = position - relativeObject.position + relativeObject.drawPosition;

            bgPos1.X = -((GameObject.relativeObject.position.X - GameObject.relativeObject.drawPosition.X) / 5) % background.Width;
            bgPos2.X = bgPos1.X + background.Width;

            for (int i = 0; i < 7 - (c.attLevel[Att.Visor]); ++i) { snowFlakesManagerBack.Add(new SnowFlake(true)); snowFlakesManagerFront.Add(new SnowFlake(false)); }
            snowFlakesManagerBack.Update(gameTime);
            snowFlakesManagerFront.Update(gameTime);
        }

        public void UpdateLevel()
        {
            for (int i = 0; i < nLevels + 1; ++i) if (H > levelHeight * i) level = i;
        }

        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(background, bgPos1, Color.White);
            spriteBatch.Draw(background, bgPos2, Color.White);
            if (isSnowing) snowFlakesManagerBack.Draw(gameTime, spriteBatch);

            bm.Draw(spriteBatch);
            c.Draw(spriteBatch);
            bm.DrawForeground(spriteBatch);

            effectsManager.Draw(gameTime, spriteBatch);
            if (isSnowing) snowFlakesManagerFront.Draw(gameTime, spriteBatch);

            // HUD
            spriteBatch.Draw(barbg, barbgPos, Color.White);
            spriteBatch.Draw(barhp, barhpPos, new Rectangle(0, 0, (int)(barhp.Width * c.hp / 100), barhp.Height), Color.White);
            spriteBatch.Draw(heart, heartPos, Color.White);
            spriteBatch.Draw(ice, icePos, Color.White);

            // debug
            if (UpUp.isDebug)
            {
                int testeX = 400;
                spriteBatch.DrawString(UpUp.Font, "HP: " + c.hp.ToString("0.0") +
                                                  "\nSession: " + c.nSessions +
                                                  "\nLevel: " + level +
                                                  "\nAltura: " + H +
                                                  "\nCristais: " + c.crystals
                    , new Vector2(testeX, 10), Color.White);

                spriteBatch.DrawString(UpUp.Font, "VisorLevel: " + c.attLevel[Att.Visor] +
                                                  "\nCoatLevel: " + c.attLevel[Att.Coat] +
                                                  "\nBootLevel: " + c.attLevel[Att.Boot] +
                                                  "\nSpikeLevel: " + c.attLevel[Att.Spike]
                    , new Vector2(testeX + 200, 10), Color.White);

                spriteBatch.DrawString(UpUp.Font, "Block 1: " + bm.block[0].filePath +
                                                  "\nBlock 2: " + bm.block[1].filePath
                    , new Vector2(testeX + 400, 10), Color.White);
            }

            if (showHotkeys)
            {
                spriteBatch.Draw(GameScreenManager.blackScreen, Vector2.Zero, new Color(0f, 0f, 0f, .85f));
                spriteBatch.DrawString(UpUp.Font, "Left/Right: move\n" +
                                                  "Up/Space: jump\n" +
                                                  "Backspace: suicide (for test)\n" +
                                                  "Enter: toggle snow (for test)\n" +
                                                  "M: toggle audio (for test)\n" +
                                                  "F2: toggle help\n" +
                                                  "F1: restart game\n" +
                                                  "Esc: exit game"
                    , new Vector2(500, 300), Color.White);
            }

            // escreve na tela a quantidade de objetos
            /*int x = 0;
            foreach (GameObject go in gameObjects) if (new Rectangle(0, 0, 1280, 720).Contains((int)go.drawPosition.X, (int)go.drawPosition.Y)) x++;
            spriteBatch.DrawString(UpUp.Font, "Game Objects: " + gameObjects.Count.ToString() + "\n On Scene: " + x, new Vector2(1100, 20), Color.White);*/

            if (isMarket) marketScreen.Draw(gameTime, spriteBatch);
            if (finished && gameOverScreen != null) gameOverScreen.Draw(gameTime, spriteBatch);
        }
    }
}